import { Alert, Tabs, TabItem } from '@aws-amplify/ui-react';
import { Example, ExampleCode } from '@/components/Example';

import {
  DefaultDarkMode,
  SystemDarkModeExample,
  CustomDarkModeExample,
} from './examples';

## Overview

Amplify UI supports color modes/schemes, like Dark Mode, through theme overrides. Amplify UI Theme Overrides let you define different theme styles in different contexts, such as color mode. You can also use plain CSS.

There are 2 ways to support light/dark mode in your application:

1. Rely on the user's OS preference (_System Preferences > General > Appearance in Mac_)
2. Place a control like a toggle button in your application that allows the user to switch color modes. With this option you could default to the OS preference or show 3 options: light, dark, system, like this site does.

Either of these approaches work with Amplify UI whether you are using the Theme Overrides or writing plain CSS.

## ThemeProvider

### colorMode

The `ThemeProvider` accepts a `colorMode` prop which can be `light`, `dark`, or `system`.

<Alert role="none" variation="warning">

If you have multiple `ThemeProvider`s in your application, make sure to store `colorMode` in the application's state or context and pass it to each `ThemeProvider` or else some parts of your app won't have the right color mode applied. Also, because the theme uses CSS variables which are inherited, your application can have some weird behavior with nested themes and color modes.

Multiple `ThemeProvider`s should be avoided if possible because it is more efficient to use a selector override instead. This site uses nested `ThemeProvider`s for demos.

</Alert>

### Default Dark Mode

Amplify UI comes with a default dark mode that you can use.

_Note: the Amplify UI theme and any overrides like dark mode are scoped to the ThemeProvider. Changing the color mode in the example will only affect the example code._

<Tabs>
  <TabItem title="JavaScript">
    <Example>
      <DefaultDarkMode />

      <ExampleCode>
```jsx
import * as React from 'react';
import {
  defaultDarkModeOverride,
  ThemeProvider,
  Card,
  Text,
  ToggleButton,
  ToggleButtonGroup,
} from '@aws-amplify/ui-react';

export const DefaultDarkMode = () => {
  const [colorMode, setColorMode] = React.useState('system');
  const theme = {
    name: 'my-theme',
    overrides: [defaultDarkModeOverride],
  };

  return (
    <ThemeProvider theme={theme} colorMode={colorMode}>
      <Card>
        <ToggleButtonGroup
          value={colorMode}
          isExclusive
          onChange={(value) => setColorMode(value)}
        >
          <ToggleButton value="light">Light</ToggleButton>
          <ToggleButton value="dark">Dark</ToggleButton>
          <ToggleButton value="system">System</ToggleButton>
        </ToggleButtonGroup>
        <Text>Current color mode: {colorMode}</Text>
      </Card>
    </ThemeProvider>
  );
};
```
        
      </ExampleCode>
    </Example>
  </TabItem>
  <TabItem title="TypeScript">
    <Example>
      <DefaultDarkMode />

      <ExampleCode>
        ```tsx file=./examples/DefaultDarkMode.tsx
        ```
        
      </ExampleCode>
    </Example>
  </TabItem>
</Tabs>

### System Dark Mode

If you don't want to provide a color mode control on your application, but still want to honor the user's operating system preference for color mode, you can set the `colorMode` on the ThemeProvider to `system`. Then use either the default dark mode override styling or provide your own.

_Note: to see dark mode applied, change your OS preferences_

<Example>
  <SystemDarkModeExample />

  <ExampleCode>
    ```tsx file=./examples/SystemDarkMode.tsx
    ```
    
</ExampleCode>
</Example>

### Custom dark mode

<Tabs>
  <TabItem title="JavaScript">
    <Example>
      <CustomDarkModeExample />
      <ExampleCode>
```jsx
import * as React from 'react';
import {
  ThemeProvider,
  Card,
  Text,
  ToggleButton,
  ToggleButtonGroup,
} from '@aws-amplify/ui-react';

export const CustomDarkModeExample = () => {
  const [colorMode, setColorMode] = React.useState('system');
  const theme = {
    name: 'my-theme',
    overrides: [
      {
        colorMode: 'dark',
        tokens: {
          colors: {
            font: {
              primary: { value: '{colors.pink.100}' },
              secondary: { value: '{colors.pink.90}' },
              tertiary: { value: '{colors.pink.80}' },
            },
            background: {
              primary: { value: '{colors.purple.10}' },
              secondary: { value: '{colors.purple.20}' },
              tertiary: { value: '{colors.purple.40}' },
            },
            border: {
              primary: { value: '{colors.pink.60}' },
              secondary: { value: '{colors.pink.40}' },
              tertiary: { value: '{colors.pink.20}' },
            },
          },
        },
      },
    ],
  };

  return (
    // Note: color mode overrides are scoped to the ThemeProvider
    // if you use multiple providers
    <ThemeProvider theme={theme} colorMode={colorMode}>
      <Card>
        <ToggleButtonGroup
          value={colorMode}
          isExclusive
          onChange={(value) => setColorMode(value)}
        >
          <ToggleButton value="light">Light</ToggleButton>
          <ToggleButton value="dark">Dark</ToggleButton>
          <ToggleButton value="system">System</ToggleButton>
        </ToggleButtonGroup>
        <Text>Current color mode: {colorMode}</Text>
      </Card>
    </ThemeProvider>
  );
};
```
      </ExampleCode>
    </Example>
  </TabItem>
  <TabItem title="TypeScript">
    <Example>
      <CustomDarkModeExample />

      <ExampleCode>
        ```tsx file=./examples/CustomDarkMode.tsx
        ```
        
      </ExampleCode>
    </Example>
  </TabItem>
</Tabs>


## CSS

You can also write CSS variables directly to support color modes. If you are using the `colorMode` prop in the `ThemeProvider`, you can write CSS like this to support dark mode:

```css
/* The prefers-color-scheme media query detects the system setting */
@media (prefers-color-scheme: dark) {
  [data-amplify-color-mode='system'] {
    --amplify-colors-background-primary: black;
  }
}

[data-amplify-color-mode='dark'] {
  --amplify-colors-background-primary: black;
}
```
